package com.hzw.saas.service.product.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.product.IUserProductService;
import com.hzw.saas.api.product.dto.UserProductDto;
import com.hzw.saas.api.product.dto.UserProductInfoDto;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.service.product.mapper.ProductMapper;
import com.hzw.saas.service.product.mapper.UserProductMapper;
import com.hzw.saas.service.product.model.Product;
import com.hzw.saas.service.product.model.UserProduct;
import cn.hutool.core.util.StrUtil;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import ma.glasnost.orika.MapperFacade;

/**
 * <p>
 * 用户产品关联表 服务实现类
 * </p>
 *
 * @author zzl
 * @since 2021-02-21
 */
@Service("userProductServiceImpl")
@RequiredArgsConstructor
public class UserProductServiceImpl extends ServiceImpl<UserProductMapper, UserProduct> implements IUserProductService, IService<UserProduct> {

    private final ProductMapper productMapper;
    private final MapperFacade mapperFacade;

    @Override
    public UserProductDto getUserProduct(String userId, String productId) {
        // 校验
        if (StrUtil.hasBlank(userId, productId))
            return new UserProductDto();
        // 查询
        List<UserProduct> list = this.lambdaQuery()
            .eq(UserProduct::getUserId, userId)
            .eq(UserProduct::getProductId, productId)
            .orderByDesc(UserProduct::getStartDate)
            .list();
        // 无结果
        if (list.size() == 0)
            return new UserProductDto();
        // 获取有效结果
        UserProduct userProduct = list.get(0);
        // 删除无效结果
        if (list.size() > 1) {
            list.remove(0);
            list.forEach(e -> this.removeById(e.getId()));
        }
        return mapperFacade.map(userProduct, UserProductDto.class);
    }

    @Override
    public int countUserProduct(String userId, Integer subStatus) {
        List<UserProduct> userProductList = this.lambdaQuery().eq(UserProduct::getUserId, userId).eq(UserProduct::getSubStatus, 1).list();
        List<String> productIdList = new ArrayList<>();
        userProductList.forEach(userProduct -> {
            productIdList.add(userProduct.getProductId());
        });
        if (Objects.equals(1, subStatus)) {
            return productIdList.size() > 0 ? productMapper.selectCount(Wrappers.<Product>lambdaQuery().in(Product::getProdId, productIdList)) : 0;
        }
        if (Objects.equals(0, subStatus)) {
            return productMapper.selectCount(Wrappers.<Product>lambdaQuery().notIn(productIdList.size() > 0, Product::getProdId, productIdList));
        }
        return productMapper.selectCount(Wrappers.query());

    }

    @Override
    public List<UserProductInfoDto> listUserProductInfo(String userId, Integer subStatus, Integer cloudType) {
        List<UserProduct> userProductList = this.lambdaQuery().eq(UserProduct::getUserId, userId).eq(UserProduct::getSubStatus, 1).list();
        List<String> productIdList = new ArrayList<>();
        userProductList.forEach(userProduct -> {
            productIdList.add(userProduct.getProductId());
        });
        List<UserProductInfoDto> userProductInfoDtoList = new ArrayList<>();
        if (Objects.equals(1, subStatus) || subStatus == null || subStatus < 0) {
            List<Product> productList = productIdList.size() > 0 ?
                productMapper.selectList(Wrappers.<Product>lambdaQuery().eq(cloudType != null && cloudType > 0, Product::getCloudType, cloudType)
                    .in(Product::getProdId, productIdList)) :
                new ArrayList<>();
            for (Product product : productList) {
                UserProductInfoDto userProductInfoDto = mapperFacade.map(product, UserProductInfoDto.class);
                for (UserProduct userProduct : userProductList) {
                    if (Objects.equals(userProduct.getProductId(), userProductInfoDto.getProdId())) {
                        mapperFacade.map(userProduct, userProductInfoDto);
                        break;
                    }
                }
                userProductInfoDto.onReady();
                userProductInfoDtoList.add(userProductInfoDto);
            }
        }
        if (Objects.equals(0, subStatus) || subStatus == null || subStatus < 0) {
            List<Product> productList = productMapper.selectList(Wrappers.<Product>lambdaQuery().eq(cloudType != null && cloudType > 0, Product::getCloudType, cloudType)
                .notIn(productIdList.size() > 0, Product::getProdId, productIdList));
            for (Product product : productList) {
                UserProductInfoDto userProductInfoDto = mapperFacade.map(product, UserProductInfoDto.class);
                userProductInfoDto.onReady();
                userProductInfoDtoList.add(userProductInfoDto);
            }
        }

        return userProductInfoDtoList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserProductDto subscribe(UserProductDto userProductDto) {
        boolean condition = StringUtils.isBlank(userProductDto.getUserId()) || StringUtils.isBlank(userProductDto.getProductId());
        AssertUtil.assertThrow("产品订阅参数异常", HttpStatus.BAD_REQUEST, condition);

        UserProduct userProduct = mapperFacade.map(userProductDto, UserProduct.class);
        if (userProduct.getSubStatus() == null) {
            userProduct.setSubStatus(1);
        }
        if (userProduct.getStartDate() == null && userProduct.getSubStatus() == 1) {
            userProduct.setStartDate(new Date());
        }
        this.remove(Wrappers.<UserProduct>lambdaQuery().eq(UserProduct::getUserId, userProduct.getUserId()).eq(UserProduct::getProductId, userProduct.getProductId()));
        this.save(userProduct);
        userProductDto.setProductId(userProduct.getProductId());
        return userProductDto;
    }

    @Override
    public UserProductDto delete(String userId, String productId) {
        AssertUtil.assertThrow("产品订阅更新参数异常", HttpStatus.BAD_REQUEST, StringUtils.isBlank(userId) || StringUtils.isBlank(productId));
        UserProduct userProduct = lambdaQuery().eq(UserProduct::getUserId, userId).eq(UserProduct::getProductId, productId).one();
        this.remove(Wrappers.<UserProduct>lambdaQuery().eq(UserProduct::getUserId, userId).eq(UserProduct::getProductId, productId));
        return mapperFacade.map(userProduct, UserProductDto.class);
    }
}
